package org.quadbac.converter;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.quadbac.measurements.LinearTransform;
import org.quadbac.measurements.MeasurementType;
import org.quadbac.measurements.Unit;

import android.app.Activity;
import android.content.Context;

public class TypesIO {

	public static ArrayList<MeasurementType> loadTypesExternal(String filePath) {
		FileInputStream mTypesFile = null;
		try {
			mTypesFile = new FileInputStream(filePath);
		} catch (FileNotFoundException e) {
			return null;
		}

		return parseJSON(loadTypes(mTypesFile));
	}

	public static void saveTypesExternal(String filePath, ArrayList<MeasurementType> mTypes) {

		String mTypesString = encodeJSON(mTypes);
		FileOutputStream mTypesStream = null;
		try {
			mTypesStream = new FileOutputStream(filePath);
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		saveTypes(mTypesStream, mTypesString);
	}

	public static ArrayList<MeasurementType> loadTypesLocal(Activity callingActivity, String filename) {
		FileInputStream mTypesFile = null;
		try {
			mTypesFile = callingActivity.openFileInput(filename);
		} catch (FileNotFoundException e) {
			return null;
		}

		return  parseJSON(loadTypes(mTypesFile));
	}


	public static void saveTypesLocal(Activity callingActivity, String filename, ArrayList<MeasurementType> mTypes) {

		String mTypesString = encodeJSON(mTypes);
		FileOutputStream mTypesStream = null;
		try {
			mTypesStream = callingActivity.openFileOutput(filename, Context.MODE_PRIVATE);
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		saveTypes(mTypesStream, mTypesString);
	}

	private static String loadTypes(FileInputStream mTypesFile) {
		StringBuilder sb = null;
		try {
			InputStreamReader isr = new InputStreamReader(mTypesFile);
			BufferedReader br = new BufferedReader(isr);
			sb = new StringBuilder();
			String s = new String();
			while ((s = br.readLine()) != null){
				sb.append(s);
			}
			br.close();
			isr.close();
			mTypesFile.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return sb.toString();
	}

	private static void saveTypes(FileOutputStream mTypesStream, String mTypesString) {

		try {
			mTypesStream.write(mTypesString.getBytes());
			mTypesStream.close();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static String encodeJSON(ArrayList<MeasurementType> mTypes) {
		JSONArray mTypesJSON = new JSONArray();
		try {
			for (MeasurementType mT : mTypes){
				JSONObject mTypeJSON = new JSONObject();
				mTypeJSON.put("mTypeName", mT.getTypeName());
				mTypeJSON.put("mTypeSymbol", mT.getTypeSymbol());
				JSONArray unitsJSON = new JSONArray();
				for (Unit u : mT.getTypeUnits()){
					JSONObject unitJSON = new JSONObject();
					unitJSON.put("unitName", u.getUnitName());
					unitJSON.put("unitSymbol", u.getUnitSymbol());
					unitJSON.put("unitOffset", ((LinearTransform)u.getUnitTransform()).getOffset());
					unitJSON.put("unitMultiplier", ((LinearTransform)u.getUnitTransform()).getMultiplier());
					unitsJSON.put(unitJSON);
				}
				mTypeJSON.put("mTypeUnits", unitsJSON);
				mTypesJSON.put(mTypeJSON);
			}
		} catch (JSONException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return mTypesJSON.toString();
	}

	private static ArrayList<MeasurementType> parseJSON(String mtypesJSONstring) {
		ArrayList<MeasurementType> mTypes = new ArrayList<MeasurementType>();
		try {
			JSONArray mTypesJSON = new JSONArray(mtypesJSONstring);
			int arrayLength = mTypesJSON.length();
			for (int i = 0; i < arrayLength; i++){
				JSONObject mTypeJSON = mTypesJSON.getJSONObject(i);
				String typeName = mTypeJSON.getString("mTypeName");
				String typeSymbol = mTypeJSON.getString("mTypeSymbol");
				MeasurementType mType = new MeasurementType(typeName, typeSymbol);
				JSONArray unitsJSON = mTypeJSON.getJSONArray("mTypeUnits");
				int unitsLength = unitsJSON.length();
				for (int j = 0; j < unitsLength; j++){
					JSONObject unitJSON = unitsJSON.getJSONObject(j);
					String unitName = unitJSON.getString("unitName");
					String unitSymbol = unitJSON.getString("unitSymbol");
					Double unitOffset = unitJSON.getDouble("unitOffset");
					Double unitMultiplier = unitJSON.getDouble("unitMultiplier");
					Unit unit = new Unit(unitName, unitSymbol, new LinearTransform(unitOffset, unitMultiplier));
					mType.add(unit);
				}
				mTypes.add(mType);
			}
		} catch (JSONException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		if (mTypes.size() > 0){
			return mTypes;
		} else {
			return null;
		}
	}
}
